`include "PRV564Config.v"
`include "PRV564Define.v"
//////////////////////////////////////////////////////////////////////////////////////////////////
//  Date    : 2021                                                                              //
//  Author  : Jack.Pan                                                                          //
//  Desc    : FIB 主机仲裁器，用于多个FIB主机共享一个FIB通道使用                                   //
//  Version : 0.0( Original Version)                                                           //
/////////////////////////////////////////////////////////////////////////////////////////////////
module FIB_arb
#(
    parameter MASTER_NUM = 4                            //DO NOT TOUCH!
)
(
    input wire                  CLKi,
    input wire                  ARSTi,
//-------------FIB master request-------------------
    input wire [MASTER_NUM-1:0]   Master_REQ,         //请求访问的Master
    output reg [MASTER_NUM-1:0]   Master_ACK          //允许访问的Master
    
);
    localparam FIB_M0 = 4'h0,        //Master0  <-- Highest privity
               FIB_M1 = 4'h1,        //Master1 
               FIB_M2 = 4'h2,        //Master2 
               FIB_M3 = 4'h3,        //Master3 
               FIB_M4 = 4'h4,        //Master4 is not use
               FIB_IDLE = 4'hf;
    reg [7:0] Select_FSM;
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        Select_FSM <= FIB_IDLE;
    end
    else begin
        case(Select_FSM)
            FIB_M0  :begin
                        if(Master_REQ[0])begin
                            Select_FSM <= Select_FSM;   //current M0 is using bus
                        end
                        else if(Master_REQ[1])begin
                            Select_FSM <= FIB_M1;
                        end
                        else if(Master_REQ[2])begin
                            Select_FSM <= FIB_M2;
                        end
                        else if(Master_REQ[3])begin
                            Select_FSM <= FIB_M3;
                        end
                     end
            FIB_M1  :begin
                        if(Master_REQ[1])begin
                            Select_FSM <= Select_FSM;   //current M0 is using bus
                        end
                        else if(Master_REQ[0])begin
                            Select_FSM <= FIB_M0;
                        end
                        else if(Master_REQ[2])begin
                            Select_FSM <= FIB_M2;
                        end
                        else if(Master_REQ[3])begin
                            Select_FSM <= FIB_M3;
                        end
                     end
            FIB_M2  :begin
                        if(Master_REQ[2])begin
                            Select_FSM <= Select_FSM;   //current M0 is using bus
                        end
                        else if(Master_REQ[0])begin
                            Select_FSM <= FIB_M0;
                        end
                        else if(Master_REQ[1])begin
                            Select_FSM <= FIB_M1;
                        end
                        else if(Master_REQ[3])begin
                            Select_FSM <= FIB_M3;
                        end
                     end
            FIB_M3  :begin
                        if(Master_REQ[3])begin
                            Select_FSM <= Select_FSM;   //current M0 is using bus
                        end
                        else if(Master_REQ[0])begin
                            Select_FSM <= FIB_M0;
                        end
                        else if(Master_REQ[1])begin
                            Select_FSM <= FIB_M1;
                        end
                        else if(Master_REQ[2])begin
                            Select_FSM <= FIB_M2;
                        end
                     end
            FIB_IDLE:begin
                        if(Master_REQ[0])begin
                            Select_FSM <= FIB_M0;   //current M0 is using bus
                        end
                        else if(Master_REQ[1])begin
                            Select_FSM <= FIB_M1;
                        end
                        else if(Master_REQ[2])begin
                            Select_FSM <= FIB_M2;
                        end
                        else if(Master_REQ[3])begin
                            Select_FSM <= FIB_M3;
                        end
                     end
            default :begin
                        if(Master_REQ[0])begin
                            Select_FSM <= FIB_M0;   //current M0 is using bus
                        end
                        else if(Master_REQ[1])begin
                            Select_FSM <= FIB_M1;
                        end
                        else if(Master_REQ[2])begin
                            Select_FSM <= FIB_M2;
                        end
                        else if(Master_REQ[3])begin
                            Select_FSM <= FIB_M3;
                        end
                     end
        endcase
    end
end
always@(*)begin
    case(Select_FSM)
        FIB_IDLE :begin
                    if(Master_REQ[0])begin
                        Master_ACK = 4'b0001;
                    end
                    else if(Master_REQ[1])begin
                        Master_ACK = 4'b0010;
                    end
                    else if(Master_REQ[2])begin
                        Master_ACK = 4'b0100;
                    end
                    else if(Master_REQ[3])begin
                        Master_ACK = 4'b1000;
                    end
                    else begin
                        Master_ACK = 4'b0000;
                    end
                  end
        FIB_M0   :begin
                    if(Master_REQ[0])begin
                        Master_ACK = 4'b0001;
                    end
                    else if(Master_REQ[1])begin
                        Master_ACK = 4'b0010;
                    end
                    else if(Master_REQ[2])begin
                        Master_ACK = 4'b0100;
                    end
                    else if(Master_REQ[3])begin
                        Master_ACK = 4'b1000;
                    end
                    else begin
                        Master_ACK = 4'b0000;
                    end
                  end
        FIB_M1   :begin
                    if(Master_REQ[1])begin
                        Master_ACK = 4'b0010;
                    end
                    else if(Master_REQ[0])begin
                        Master_ACK = 4'b0001;
                    end
                    else if(Master_REQ[2])begin
                        Master_ACK = 4'b0100;
                    end
                    else if(Master_REQ[3])begin
                        Master_ACK = 4'b1000;
                    end
                    else begin
                        Master_ACK = 4'b0000;
                    end
                  end
        FIB_M2   :begin
                    if(Master_REQ[2])begin
                        Master_ACK = 4'b0100;
                    end
                    else if(Master_REQ[0])begin
                        Master_ACK = 4'b0001;
                    end
                    else if(Master_REQ[1])begin
                        Master_ACK = 4'b0010;
                    end
                    else if(Master_REQ[3])begin
                        Master_ACK = 4'b1000;
                    end
                    else begin
                        Master_ACK = 4'b0000;
                    end
                  end
        FIB_M3   :begin
                    if(Master_REQ[3])begin
                        Master_ACK = 4'b1000;
                    end
                    else if(Master_REQ[0])begin
                        Master_ACK = 4'b0001;
                    end
                    else if(Master_REQ[1])begin
                        Master_ACK = 4'b0010;
                    end
                    else if(Master_REQ[2])begin
                        Master_ACK = 4'b0100;
                    end
                    else begin
                        Master_ACK = 4'b0000;
                    end
                  end
        default  : Master_ACK = 4'b0000;
    endcase
end

endmodule